module obs_operator_types_mod

  use const_mod

  implicit none

  type obs_grid_connector_type
    real(r8) obs_lon ! deg
    real(r8) obs_lat ! deg
    real(r8) obs_alt ! m
    real(r8), allocatable :: obs_zlev(:) ! m
    real(r8), allocatable :: obs_plev(:) ! hPa
    logical :: around_zero_lon = .false.
    integer :: num_grid = 0
    integer, allocatable :: grid_idx(:,:)
    real(r8), allocatable :: grid_wgt(:)
    class(*), pointer :: record => null()
  contains
    procedure :: init => obs_grid_connector_init
    procedure :: clear => obs_grid_connector_clear
    final :: obs_grid_connector_final
  end type obs_grid_connector_type

contains

  subroutine obs_grid_connector_init(this, num_grid, idx_size, record, obs_alt, obs_zlev, obs_plev)

    class(obs_grid_connector_type), intent(out) :: this
    integer, intent(in) :: num_grid
    integer, intent(in) :: idx_size
    class(*), intent(in), target :: record
    real, intent(in), optional :: obs_alt
    real, intent(in), optional :: obs_zlev(:)
    real, intent(in), optional :: obs_plev(:)

    call this%clear()

    this%num_grid = num_grid
    this%record => record

    allocate(this%grid_idx(idx_size,num_grid))
    allocate(this%grid_wgt(num_grid))

    if (present(obs_alt)) then
      this%obs_alt = obs_alt
    end if

    if (present(obs_zlev)) then
      allocate(this%obs_zlev(size(obs_zlev)))
      this%obs_zlev = obs_zlev
    end if

    if (present(obs_plev)) then
      allocate(this%obs_plev(size(obs_plev)))
      this%obs_plev = obs_plev
    end if

  end subroutine obs_grid_connector_init

  subroutine obs_grid_connector_clear(this)

    class(obs_grid_connector_type), intent(inout) :: this

    this%around_zero_lon = .false.
    if (allocated(this%obs_zlev)) deallocate(this%obs_zlev)
    if (allocated(this%obs_plev)) deallocate(this%obs_plev)
    if (allocated(this%grid_idx)) deallocate(this%grid_idx)
    if (allocated(this%grid_wgt)) deallocate(this%grid_wgt)

  end subroutine obs_grid_connector_clear

  subroutine obs_grid_connector_final(this)

    type(obs_grid_connector_type), intent(inout) :: this

    call this%clear()

  end subroutine obs_grid_connector_final

end module obs_operator_types_mod
